#include <stdio.h>
#include <unistd.h>

#include <cctype>
#include <iostream>
#include <tuple>

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/InetAddress.h"
#include "muduo/net/TcpClient.h"
#include "muduo/net/TcpServer.h"
using namespace muduo;
using namespace muduo::net;
using std::string;
EventLoop loop;
string PORT{"9983"};
string DOMAIN{"localhost"};
std::string message = PORT + DOMAIN;
string get_port(const string & s_port)
{
    int16_t port = stoi(s_port);
    string res_port;
    while(port) {
        res_port.push_back(char(port));
        port>>=8;
    }
    return {res_port.rbegin(), res_port.rend()};
}
string sizeToString(const string& port, const string &domain);
string sizeToString(const string & port_domain)
{
    int k = -1;
    while(std::isdigit(port_domain[++k]));
    return sizeToString(port_domain.substr(0, k), port_domain.substr(k));
}
string sizeToString(const string& port, const string &domain)
{
    string res{"\003\001"};
    res.append(get_port(port));
#ifndef DEBUG
    std::cout << port << "port\n";
#endif
    res.push_back('\000');
    res.push_back('\000');
    res.push_back('\000');
    res.push_back('\001');
    res.push_back('\000');
    res += domain;
    res.push_back('\0');
    for (auto c : res) std::cout << c << '\n';
    std::cout << res.size() << '\n';
    std::cout << res << '\n';
    return res;
}
void onConnection(const TcpConnectionPtr& conn)
{
    if (conn->connected()) {
        std::cout << "establish" << std::endl;
     
        conn->send(sizeToString(message));
    } else {
        printf("onConnection(): connection [%s] is down\n", conn->name().c_str());
        // conn->shutdown();
        loop.quit();
    }
}

void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp receiveTime)
{
    printf("onMessage(): received %zd bytes from connection [%s] at %s\n",
             buf->readableBytes(),
             conn->name().c_str(),
             receiveTime.toFormattedString().c_str());

    printf("onMessage(): [%s]\n", buf->retrieveAsString(buf->readableBytes()).c_str());
}

int main(int argc, char ** argv)
{
    if(argc > 1) {
        message = argv[1] + DOMAIN;
    }
    InetAddress serverAddr("localhost", 9981);
    TcpClient client(&loop, serverAddr, "123");
    std::cout << message << std::endl;
    client.setConnectionCallback(onConnection);
    client.setMessageCallback(onMessage);
    client.enableRetry();
    client.connect();
    loop.loop();
}
